package com.glodon.paas.account.security.oauth1.provider;

import net.oauth.OAuthException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.glodon.paas.account.dao.OAuthTokenDao;
import com.glodon.paas.account.dao.domain.OAuthTokenEntity;
import com.glodon.paas.util.TokenUtil;

/**
 * 
 * @author guojf
 * 
 */
@Component
public class OAuthTokenManagerImpl implements OAuthTokenManager {
	@Autowired
	private OAuthTokenDao tokenStore;
	
//	@Autowired
//	private OAuthAuthorizationDao authorizationDao;

	private final int requestTokenValiditySeconds = 60 * 10;
	private final int accessTokenValiditySeconds = 60 * 60 * 12;
	

	private boolean isExpired(OAuthTokenEntity token) {
		long expiredTime = token.getTimestamp()
				+ (token.isAccessToken()
						? accessTokenValiditySeconds * 1000
						: requestTokenValiditySeconds) * 1000;
		return System.currentTimeMillis() > expiredTime;
	}

	/* (non-Javadoc)
	 * @see com.glodon.paas.account.security.oauth1.provider.OAuthTokenManager#getToken(java.lang.String)
	 */
	@Override
	public OAuthTokenEntity getToken(String tokenValue) throws OAuthException {
		OAuthTokenEntity token = tokenStore.readToken(tokenValue);

		if (token == null) {
			throw new OAuthException("Invalid token: " + tokenValue);
		}

		return token;
	}
	
	/* (non-Javadoc)
	 * @see com.glodon.paas.account.security.oauth1.provider.OAuthTokenManager#removeToken(java.lang.String)
	 */
	@Override
	public OAuthTokenEntity removeToken(String tokenValue) throws OAuthException {
		return tokenStore.removeToken(tokenValue);
	}

	/* (non-Javadoc)
	 * @see com.glodon.paas.account.security.oauth1.provider.OAuthTokenManager#createUnauthorizedRequestToken(java.lang.String, java.lang.String)
	 */
	@Override
	public OAuthTokenEntity createUnauthorizedRequestToken(String consumerKey, String callbackUrl) {
		OAuthTokenEntity token = new OAuthTokenEntity();
		token.setAccessToken(false);
		token.setAuthorized(false);
		token.setConsumerKey(consumerKey);
		token.setCallbackUrl(callbackUrl);
		token.setUserId(null);
		token.setSecret(TokenUtil.newTokenSecret());
		token.setValue(TokenUtil.newTokenValue());
		token.setTimestamp(System.currentTimeMillis());
		tokenStore.insert(token);
		return token;
	}

	/* (non-Javadoc)
	 * @see com.glodon.paas.account.security.oauth1.provider.OAuthTokenManager#authorizeRequestToken(java.lang.String, java.lang.String, com.glodon.paas.account.dao.domain.OAuthAuthorizationEntity)
	 */
	@Override
	public void authorizeRequestToken(String requestToken, String verifier, String userId) throws OAuthException {
		OAuthTokenEntity token = tokenStore.readToken(requestToken);

		if (token == null) {
			throw new OAuthException("Invalid token: " + requestToken);
		} else if (isExpired(token)) {
			tokenStore.removeToken(requestToken);
			throw new OAuthException("Expired token: " + requestToken);
		} else if (token.isAccessToken()) {
			throw new OAuthException("Request to authorize an access token.");
		}
//		if(StringUtils.isEmpty(authorization.getId())){
//			authorization.setId(UUID.radndomUUID().toString().replaceAll("-", ""));
//		}
		token.setUserId(userId);
		token.setTimestamp(System.currentTimeMillis());
		token.setVerifier(verifier);
		token.setAuthorized(true);
		tokenStore.saveToken(token);
	}

	/* (non-Javadoc)
	 * @see com.glodon.paas.account.security.oauth1.provider.OAuthTokenManager#createAccessToken(java.lang.String)
	 */
	@Override
	public OAuthTokenEntity createAccessToken(String requestToken) throws OAuthException {
		OAuthTokenEntity token = tokenStore.readToken(requestToken);
		if (token == null) {
			throw new OAuthException("Invalid token: " + requestToken);
		} else if (isExpired(token)) {
			tokenStore.removeToken(requestToken);
			throw new OAuthException("Expired token: " + requestToken);
		} else if (token.isAccessToken()) {
			throw new OAuthException("Request to authorize an access token.");
		}
		
//		OAuthAuthorizationEntity authorization = authorizationDao.get(token.getoAuthAuthorizationId());
//		if (authorization == null) {
//			throw new OAuthException("Request token has not been authorized.");
//		}
		//remove request token
		tokenStore.removeToken(requestToken);
		// remove old tokens for this consumerkey
		tokenStore.removeToken(token.getConsumerKey(), token.getUserId());
//		List<OAuthAuthorizationEntity> auths = authorizationDao.getAuthorizationsByUser(authorization.getUserId());
		//remove access tokens issued to the same consumer by the same user
//		for(OAuthAuthorizationEntity auth : auths){
//			if(!auth.getId().equals(authorization.getId())){
//				tokenStore.removeToken(token.getConsumerKey(), auth.getId());
//				authorizationDao.delete(auth.getId());
//			}
//		}
		
		OAuthTokenEntity accessToken = new OAuthTokenEntity();
		accessToken.setAccessToken(true);
		accessToken.setAuthorized(true);
		accessToken.setConsumerKey(token.getConsumerKey());
		accessToken.setUserId(token.getUserId());
		accessToken.setCallbackUrl(token.getCallbackUrl());
		accessToken.setSecret(TokenUtil.newTokenSecret());
		accessToken.setValue(TokenUtil.newTokenValue());
		accessToken.setTimestamp(System.currentTimeMillis());
		tokenStore.insert(accessToken);
		return accessToken;
	}
	
	/* (non-Javadoc)
	 * @see com.glodon.paas.account.security.oauth1.provider.OAuthTokenManager#getAuthorization(java.lang.String)
	 */
//	@Override
//	public OAuthAuthorizationEntity getAuthorization(String authorizationId){
//		return authorizationDao.get(authorizationId);
//	}
}
